@bridge-ds/core 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,8 @@ export declare const BUILD_REQUEST_LABEL = "bridge-build";
8
8
  export declare const SOURCE_FIGMA_LABEL = "source: figma";
9
9
  /** A build request waits this many days before it reads as stale. */
10
10
  export declare const BUILD_STALE_DAYS = 7;
11
+ /** A request closed as not planned stays in the "All" list this many days after it was closed, then leaves it. */
12
+ export declare const BUILD_DECLINED_DAYS = 7;
11
13
  /**
12
14
  * What the two images of a build request are called on designer screens (Studio): the component as it is in code
13
15
  * now, and the design in Figma. The data keeps its field names, `before` and `after`; the GitHub issue table, read by
@@ -290,6 +292,8 @@ export interface BuildPullLike {
290
292
  assignees?: string[] | undefined;
291
293
  createdAt?: string | undefined;
292
294
  updatedAt?: string | undefined;
295
+ /** When it was closed (merged or not), when known. */
296
+ closedAt?: string | null | undefined;
293
297
  body?: string | undefined;
294
298
  /** Commits on the branch, when known (a branch with only the spec commit is not work in progress). */
295
299
  commits?: number | null | undefined;
@@ -384,7 +388,12 @@ export declare function assembleBuildRequests(input: {
384
388
  /** The filters of the Being built page. */
385
389
  export type BuildFilter = 'all' | 'waiting' | 'in-progress' | 'shipped-this-week';
386
390
  export declare const BUILD_FILTER_LABEL: Record<BuildFilter, string>;
387
- /** Whether a build request shows under a filter. "All" leaves out what was closed as not planned more than a week ago. */
391
+ /** When a build request was closed as not planned, from its timeline, or null. */
392
+ export declare const declinedAt: (v: Pick<BuildRequestView, "status" | "timeline">) => string | null;
393
+ /**
394
+ * Whether a build request shows under a filter. "All" keeps a request closed as not planned for BUILD_DECLINED_DAYS
395
+ * after it was closed (one without a close date leaves at once), then leaves it out; shipped requests stay in "All".
396
+ */
388
397
  export declare function matchesBuildFilter(v: Pick<BuildRequestView, 'status' | 'shippedAt' | 'timeline'>, f: BuildFilter, now?: Date | number): boolean;
389
398
  /** Build requests still open (not shipped, not closed). */
390
399
  export declare const openBuildRequests: <V extends Pick<BuildRequestView, "status">>(views: readonly V[]) => V[];
@@ -13,6 +13,24 @@ export declare function explorationStage(x: {
13
13
  archived?: boolean | null | undefined;
14
14
  files: readonly string[] | null | undefined;
15
15
  }): 'not-started' | 'exploring' | 'handed';
16
+ /** The words of a running exploration on its page, and on every row and card that lists it. */
17
+ export declare const EXPLORATION_STAGE_LABEL: {
18
+ readonly 'not-started': "Not started";
19
+ readonly exploring: "Exploring";
20
+ readonly archived: "Archived";
21
+ };
22
+ /**
23
+ * The one status tag of an exploration wherever it is listed (Changes rows, Home cards, tools): the words its page
24
+ * shows. Running: "Not started" while the branch only carries Bridge notes, else "Exploring". Archived: "Archived".
25
+ * After done exploring: where it stands ("Waiting for code", "Being built", "Shipped"). Never a check or a technical
26
+ * blocker: an exploration's guard check fails by design. `files` undefined (not read yet): null for a running one, so
27
+ * a row never guesses; null (the read failed): "Exploring", as on the page.
28
+ */
29
+ export declare function explorationStateLabel(x: {
30
+ status: ExplorationStatus;
31
+ archived?: boolean | null | undefined;
32
+ files?: readonly string[] | null | undefined;
33
+ }): string | null;
16
34
  export interface ContinueRef {
17
35
  number: number;
18
36
  name: string;
@@ -19,6 +19,8 @@ export interface ExplorationSettings {
19
19
  labels?: string[] | undefined;
20
20
  /** Started in a product's own repository (productRepoOf): what its draft pull request body says instead of the library's. */
21
21
  inProduct?: ExplorationPrContext['inProduct'];
22
+ /** Wait between label retries, in ms (tests pass 0). */
23
+ retryMs?: number | undefined;
22
24
  }
23
25
  /** The first commit message of an exploration branch: the purpose only when one was given. */
24
26
  export declare const explorationStartMessage: (e: Pick<Exploration, "name" | "purpose">) => string;
@@ -106,6 +108,11 @@ export interface StartedExploration {
106
108
  label: string;
107
109
  url: string;
108
110
  }[];
111
+ /**
112
+ * Labels GitHub refused even after retries (labelExploration). The pull request exists: lists still read it as an
113
+ * exploration (isUnlabeledExploration) and Studio puts `exploration` back; callers say it in one line.
114
+ */
115
+ labelsMissing?: string[];
109
116
  }
110
117
  /**
111
118
  * Starts an exploration: the branch `explore/<slug>` from the base with one commit (the exploration note), a draft
@@ -113,6 +120,12 @@ export interface StartedExploration {
113
120
  * install command. Refuses an exploration whose branch already exists.
114
121
  */
115
122
  export declare function startExplorationOnGitHub(gh: GitHubClient, e: Exploration, s: ExplorationSettings): Promise<StartedExploration>;
123
+ /**
124
+ * Labels a new exploration: `exploration` on its own first, tried three times (GitHub sometimes refuses a label on a
125
+ * pull request created a moment ago), then the other labels in one more call. A label that does not exist yet (a
126
+ * product's) can fail on its own without taking `exploration` with it. Returns the labels still missing.
127
+ */
128
+ export declare function labelExploration(gh: Pick<GitHubClient, 'addLabels'>, pr: number, extra: readonly string[], retryMs?: number): Promise<string[]>;
116
129
  /** Whether Bridge can open an exploration in a product's own repository with this token, and from which branch. */
117
130
  export type ProductRepoAccess = {
118
131
  ok: true;
@@ -71,7 +71,7 @@ export declare function explorationSlugFromBranch(ref: string): string | null;
71
71
  /**
72
72
  * Which exploration a person or a tool means, wherever it lives. In the design system repository: its number ("12",
73
73
  * "#12") or its name ("pill-buttons", "explore/pill-buttons"). In a product's own repository, the product key or the
74
- * repository goes first: "shop#12", "peterbono/bridge-demo-shop#12", "shop:checkout-flow", or the pull request link.
74
+ * repository goes first: "admin-app#12", "peterbono/bridge-product-admin#12", "admin-app:checkout-flow", or the pull request link.
75
75
  */
76
76
  export interface ExplorationRef {
77
77
  /** A product key ("shop"), when the reference names one. */
@@ -152,6 +152,21 @@ export interface ExplorationPullLike {
152
152
  }
153
153
  /** True for a pull request that is or was an exploration: an `explore/*` branch, the label, or the Bridge block. */
154
154
  export declare function isExplorationPull(p: ExplorationPullLike): boolean;
155
+ /**
156
+ * A running exploration whose `exploration` label is missing, because the label call failed when it was started: an
157
+ * open draft on an `explore/*` branch or with the Bridge block, neither archived nor done exploring. Every list, page
158
+ * and status treats it as running (explorationStatus, isHeldExploration), and Studio puts the label back for a viewer
159
+ * who can write. An older promotion also removed the label, but it marked the pull request ready for review: not a draft.
160
+ */
161
+ export declare function isUnlabeledExploration(p: {
162
+ state?: string | undefined;
163
+ draft?: boolean | undefined;
164
+ labels?: readonly (string | {
165
+ name?: string;
166
+ })[] | null | undefined;
167
+ headRef?: string | null | undefined;
168
+ body?: string | null | undefined;
169
+ }): boolean;
155
170
  /** "Done exploring" was said: the `ready-for-devs` label, or the date in the exploration block. */
156
171
  export declare function isHandedOff(p: Pick<ExplorationPullLike, 'labels' | 'body'>): boolean;
157
172
  /**
@@ -161,6 +176,27 @@ export declare function isHandedOff(p: Pick<ExplorationPullLike, 'labels' | 'bod
161
176
  * done exploring is the older promotion: promoted, open or merged.
162
177
  */
163
178
  export declare function explorationStatus(p: ExplorationPullLike): ExplorationStatus;
179
+ /**
180
+ * The pull request is an exploration right now: open with the `exploration` label (archived ones keep it), or a running
181
+ * exploration whose label is missing (isUnlabeledExploration: an open draft on an `explore/*` branch or with the
182
+ * Bridge block). Its guard check (EXPLORATION_CHECK) fails by design then, so every check summary leaves that check out
183
+ * (review-gate summarizeCi `exploration`): Studio, the MCP server and the CLI never read it as a problem. Any other
184
+ * pull request with that check failing still counts it.
185
+ */
186
+ export declare function isGuardedExploration(p: {
187
+ state?: string | undefined;
188
+ draft?: boolean | undefined;
189
+ labels?: readonly (string | {
190
+ name?: string;
191
+ })[] | null | undefined;
192
+ headRef?: string | null | undefined;
193
+ head?: {
194
+ ref?: string | null | undefined;
195
+ } | null | undefined;
196
+ body?: string | null | undefined;
197
+ }): boolean;
198
+ /** True for the guard check of an exploration (EXPLORATION_CHECK), by check run name or status context. */
199
+ export declare const isExplorationCheck: (name: string | null | undefined) => boolean;
164
200
  /** True while the label is on: the pull request must not merge (the CI check fails, Studio blocks the merge). */
165
201
  export declare const isActiveExploration: (labels: ExplorationPullLike["labels"]) => boolean;
166
202
  /** True for an archived exploration: hidden from the default lists, reachable from the Archived filter. */
@@ -177,6 +213,12 @@ export declare function isHeldExploration(p: {
177
213
  labels?: readonly (string | {
178
214
  name?: string;
179
215
  })[] | null | undefined;
216
+ /** The branch and the body: a running exploration whose label is missing is held too (isUnlabeledExploration). */
217
+ headRef?: string | null | undefined;
218
+ head?: {
219
+ ref?: string | null | undefined;
220
+ } | null | undefined;
221
+ body?: string | null | undefined;
180
222
  }): boolean;
181
223
  /** How a developer takes an exploration: fetch, then check out its branch. */
182
224
  export declare const explorationTakeCommands: (branch: string) => [string, string];
@@ -605,8 +605,13 @@ export declare class GitHubClient {
605
605
  /** Every file path at a ref (branch, tag or sha), one API call. */
606
606
  listFiles(ref: string): Promise<string[]>;
607
607
  listPullRequests(state?: 'open' | 'closed' | 'all'): Promise<PullRequestSummary[]>;
608
- /** Commit statuses and check runs of a commit, folded into one state. */
609
- getChecks(sha: string): Promise<{
608
+ /**
609
+ * Commit statuses and check runs of a commit, folded into one state. `exploration`: the commit heads an exploration
610
+ * (explorations isGuardedExploration), so its guard check, failing by design, is left out (as review-gate summarizeCi).
611
+ */
612
+ getChecks(sha: string, opts?: {
613
+ exploration?: boolean | undefined;
614
+ }): Promise<{
610
615
  state: 'success' | 'failure' | 'pending' | 'none';
611
616
  checks: {
612
617
  name: string;